/*
 * Sachovnice.java
 *
 * Created on 18. �erven 2007, 19:56
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package cz.possoft.serializable.chess.game;

import cz.possoft.serializable.chess.figurky.Figurka;
import cz.possoft.serializable.chess.figurky.King;
import cz.possoft.serializable.chess.figurky.Pesec;
import cz.possoft.serializable.chess.figurky.Prazdna;
import cz.possoft.serializable.chess.figurky.Queen;
import cz.possoft.serializable.chess.figurky.Rider;
import cz.possoft.serializable.chess.figurky.Shooter;
import cz.possoft.serializable.chess.figurky.Tower;
import cz.possoft.serializable.generic.HraciPole;
import cz.possoft.serializable.generic.Location;

/**
 * Predstavuje sachovnici pro hru sachy
 *
 * @author mara
 */
public class ChessPole extends HraciPole {
	
	public static final long serialVersionUID = 100458945;
    
    private Figurka figurky[][];
    
    private Location whiteKingLocation;
    private Location blackKingLocation;
    
    // souradnice posledniho tahu. Udrzuje se kvuli moznosti tahu en passant
    private int[] lastTah = {0, 0, 0, 0};

    public int[] getLastTah() {
        return lastTah;
    }
    
    public void setLastTah(int x1, int y1, int x2, int y2) {
        lastTah[0] = x1;
        lastTah[1] = y1;
        lastTah[2] = x2;
        lastTah[3] = y2;
    }
    
    /** Creates a new instance of ChessPole */
    public ChessPole(boolean novaHra) {
        setFigurky(new Figurka[8][8]);
        
        if (novaHra) { loadFigurkyAfterNewGame(); 
                   }
        else { loadEmptySachovnice(); }        
    }        

    public Location getBlackKingLocation() {
        return blackKingLocation;
    }

    public void setBlackKingLocation(Location blackKingLocation) {
        this.blackKingLocation = blackKingLocation;
    }

    public Location getWhiteKingLocation() {
        return whiteKingLocation;
    }

    public void setWhiteKingLocation(Location whiteKingLocation) {
        this.whiteKingLocation = whiteKingLocation;
    }
    
    
    
    // Pocatecni nacteni figurek na sachovnici po startu nove hry
    public void loadFigurkyAfterNewGame() {
        
        // nacteni cernych
        getFigurky()[0][0]=new Tower(0,0,1,this);
        getFigurky()[1][0]=new Rider(1,0,1,this);
        getFigurky()[2][0]=new Shooter(2,0,1,this);
        getFigurky()[3][0]=new Queen(3,0,1,this);
        getFigurky()[4][0]=new King(4,0,1,this);
        getFigurky()[5][0]=new Shooter(5,0,1,this);
        getFigurky()[6][0]=new Rider(6,0,1,this);
        getFigurky()[7][0]=new Tower(7,0,1,this);
        for (int i=0;i<8;i++) getFigurky()[i][1]=new Pesec(i,1,1,this);
        
        // nacteni prazdnych
        for (int i=2;i<6;i++)
            for (int j=0;j<8;j++) getFigurky()[j][i]=new Prazdna(j,i,this);
        
        // nacteni bilych
        for (int i=0;i<8;i++) getFigurky()[i][6]=new Pesec(i,6,2,this);
        getFigurky()[0][7]=new Tower(0,7,2,this);
        getFigurky()[1][7]=new Rider(1,7,2,this);
        getFigurky()[2][7]=new Shooter(2,7,2,this);
        getFigurky()[3][7]=new Queen(3,7,2,this);
        getFigurky()[4][7]=new King(4,7,2,this);
        getFigurky()[5][7]=new Shooter(5,7,2,this);
        getFigurky()[6][7]=new Rider(6,7,2,this);
        getFigurky()[7][7]=new Tower(7,7,2,this);
        
        setBlackKingLocation(new Location(4, 0));
        setWhiteKingLocation(new Location(4, 7));
    }
    
    public void loadEmptySachovnice() {
        // nacteni prazdnych
        for (int i=0;i<8;i++)
            for (int j=0;j<8;j++) getFigurky()[j][i]=new Prazdna(j,i,this);
    }

    public Figurka[][] getFigurky() {
        return figurky;
    }

    public void setFigurky(Figurka[][] figurky) {
        this.figurky = figurky;
    }
    
    // vraci figurku na dane pozici
    public Figurka getFigurka(int x, int y) {
        return figurky[x][y];
    }
    
    // nasetuje figurku na dane pozici
    public void setFigurka(int x, int y, Figurka fig) {
        figurky[x][y] = fig;
    }
    
    // vraci true pokud je sachovnice ve stavu, ze ma kral zadane barvy(na souradnicich x,y) sach
    public boolean isSach(int color, int x, int y) {
        //System.out.println("color:" + color + " x:" + x + ", y:" + y);
        // 1) sach z uhlopricek (strelec, dama, kral pro vzd = 1)        
        int xyState[][] = {{-1,-1}, {-1,1}, {1,-1}, {1,1}};
        int xNow;
        int yNow;
        for (int i=0; i<xyState.length; i++) {
            boolean b = true;            
            xNow = x + xyState[i][0];
            yNow = y + xyState[i][1];
            int pom=0;
            while (b && (xNow >-1) && (xNow < 8) && (yNow > -1) && (yNow < 8)) {
                pom++;                
                Figurka fig = getFigurka(xNow, yNow);
                if (fig.getColor() != 0) {
                    if ((fig.getColor() != color) && ((fig instanceof Shooter) || (fig instanceof Queen) || ((pom == 1) && (fig instanceof King)))) return true;
                    else b = false;
                }
                xNow = xNow + xyState[i][0];
                yNow = yNow + xyState[i][1];
            }            
        }        
        //System.out.println("Kontrola sachu z strelcu - false");
        
        // 2) sach z delek (vez, dama, kral pro vzd = 1)
        int xyState2[][] = {{-1,0}, {1,0}, {0,-1}, {0,1}};        
        for (int i=0; i<xyState2.length; i++) {
            boolean b = true;            
            xNow = x + xyState2[i][0];
            yNow = y + xyState2[i][1];
            int pom=0;
            while (b && (xNow >-1) && (xNow < 8) && (yNow > -1) && (yNow < 8)) {
                pom++;                
                Figurka fig = getFigurka(xNow, yNow);
                if (fig.getColor() != 0) {
                    if ((fig.getColor() != color) && ((fig instanceof Tower) || (fig instanceof Queen) || ((pom == 1) && (fig instanceof King)))) return true;
                    else b = false;
                }
                xNow = xNow + xyState2[i][0];
                yNow = yNow + xyState2[i][1];
            }            
        }
        //System.out.println("Kontrola sachu od vezi - false");
        
        // 3) sach od pescu
        if ((color == 1) && (y != 7)) {
            if (x != 7) {
                Figurka fig1 = getFigurka(x+1, y+1);
                if ((fig1.getColor()==2) && (fig1 instanceof Pesec)) return true;
            } 
            if (x != 0) {
                Figurka fig1 = getFigurka(x-1, y+1);
                if ((fig1.getColor()==2) && (fig1 instanceof Pesec)) return true;
            } 
        }
        if ((color == 2) && (y != 0)) {
            if (x != 7) {
                Figurka fig1 = getFigurka(x+1, y-1);
                if ((fig1.getColor()==1) && (fig1 instanceof Pesec)) return true;
            } 
            if (x != 0) {
                Figurka fig1 = getFigurka(x-1, y-1);
                if ((fig1.getColor()==1) && (fig1 instanceof Pesec)) return true;
            } 
        }
        //System.out.println("Kontrola sachu od pescu - false");
        
        // sach od jezdcu
        int xyState3[][] = {{-2,-1}, {-2,1}, {-1,-2}, {-1,2}, {2,-1}, {2,1}, {1,-2}, {1,2}};  
        for (int i=0; i<xyState3.length; i++) {                  
            xNow = x + xyState3[i][0];
            yNow = y + xyState3[i][1];
            if ((xNow >-1) && (xNow < 8) && (yNow > -1) && (yNow < 8)) {
                Figurka fig1 = getFigurka(xNow, yNow);
                if ((fig1.getColor() != color) && (fig1 instanceof Rider)) return true;
            }
        }
        //System.out.println("Kontrola sachu od jezdcu - false");
        return false;
    }
    
    // vraci signum
    private int sgn(int x) {
        if (x>0) return 1;
        if (x<0) return -1;
        return 0;
    }
    
    // podle barvy krale a jeho souradnic a figurky co dala sach zjisti, jestli ej hra ve stavu sach mat.
    public boolean isSachMat(int color, int x, int y, Figurka fig) {
        // 1) zjistime jestli kral muze tahnout na nektere ze sousednich poli
       int pomPole[][] = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}};  
       King king = (King)getFigurka(x, y);
       int xNew;
       int yNew;
       for (int i=0; i<pomPole.length; i++) {
           xNew = x + pomPole[i][0];
           yNew = y + pomPole[i][1];
           if (king.muzeTahnout(xNew, yNew)) return false;
       }
       // 2) zjistime vsechny policka na ceste od figurky fig ke krali vcetne 
       // pole, na kterem stoji figurka a ukladame do pole pomPole2              
       if ((fig instanceof Rider) || (fig instanceof Pesec)) {
           if (canSomebodyGoToThisPole(color, fig.getX(), fig.getY())) return false;
       } else {
           int xs = sgn(fig.getX() - x);
           int ys = sgn(fig.getY() - y);
           int xpom = x;
           int ypom = y;
           while ((xpom != fig.getX()) || (ypom != fig.getY())) {
               xpom = xpom + xs;
               ypom = ypom + ys;
               if (canSomebodyGoToThisPole(color, xpom, ypom)) return false;
           }
       }
       return true;
    }
    
    // vraci true pokud nektera z figurek barvy color na sachovnici muze tahnout na pole x,y
    private boolean canSomebodyGoToThisPole(int color, int xpom, int ypom) {
        for (int i=0; i<8; i++)
            for (int j=0; j<8; j++) {
                Figurka fig = getFigurka(i, j);
                if (fig.getColor() == color) {
                    if (fig.muzeTahnout(xpom, ypom)) return true;
                }
            }
        return false;
    }
    
    // nastavi figurku podle toho, co doslo z pesec dialogu nebo od oponenta ze serveru
    public Figurka setFigurkaFromPesecDosel(String figClass, int x, int y, int color) {
    try {
                Figurka fig = ((Figurka)(Class.forName("cz.possoft.serializable.chess.figurky." + figClass).newInstance()));
                fig.setColor(color);
                fig.setX(x);
                fig.setY(y);
                fig.setMarked(false);
                fig.setRing(false);                
                fig.setSachovnice(this);                
                setFigurka(x, y, fig);                                
                return fig;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
}
}
